<!--
 * @Description: 普通表格组件
-->
<template>
  <div class="_ehl_table_box">
    <el-table
      :ref="ref"
      :data="tableData"
      :border="border"
      :row-key="rowKey"
      :max-height="maxHeight"
      :row-class-name="rowClassName"
      @selection-change="selectionChange"
      @sort-change="sortHandler"
      @filter-change="filterHandler"
      :default-sort="defaultSort !== '' ? { prop: defaultSort, order: 'descending' } : {}"
    >
      <template v-for="(item, index) in tableColumns">
        <!-- 用于批量操作多选 -->
        <el-table-column
          v-if="item.selection"
          :key="index"
          :type="item.selection"
          :reserve-selection="item.reserveSelection"
          :prop="item.prop"
          :label="item.label"
          :sortable="item.sortable"
          :align="item.align"
          :width="dealWidth(item.width)"
          :min-width="dealWidth(item.minWidth)"
          :column-key="item.prop"
          :filters="item.filters"
          :fixed="item.fixed"
          :sort-orders="['ascending', 'descending']"
        >
        </el-table-column>
        <!-- 操作 -->
        <el-table-column
          v-else-if="item.isOperation"
          :key="index + '-a'"
          :label="item.label"
          :align="item.align"
          :fixed="item.fixed"
          :width="dealWidth(item.width)"
        >
          <template v-slot:header="scope">
            <span
              v-if="scope.column.label && scope.column.label.indexOf('<') > -1"
              v-html="scope.column.label"
            ></span>
            <span v-else :title="scope.column.label">{{ scope.column.label }}</span>
          </template>
          <template v-slot="scope">
            <slot
              name="operation"
              :data="{
                ...scope.row,
                $rowMsg: {
                  column: scope.column,
                  index: scope.$index,
                  page: currentPage,
                  size: pageSize,
                },
              }"
            ></slot>
          </template>
        </el-table-column>
        <!-- 多选 -->
        <el-table-column
          v-else-if="item.checked"
          :key="index + '-b'"
          :prop="item.prop"
          :fixed="item.fixed"
          :width="dealWidth(item.width || '80')"
        >
          <template v-slot:header="scope">
            <el-checkbox
              v-model="allSelect"
              :indeterminate="indeterminate"
              @change="
                val => {
                  checkboxChange(val, item, scope)
                }
              "
            />
          </template>
          <template v-slot="scope">
            <el-checkbox v-model="scope.row[item.prop]" />
          </template>
        </el-table-column>
        <!-- 自定义内容 -->
        <el-table-column
          v-else-if="item.formatter"
          :key="index + '-c'"
          :prop="item.prop"
          :label="item.label"
          :sortable="item.sortable"
          :align="item.align"
          :width="dealWidth(item.width)"
          :min-width="dealWidth(item.minWidth)"
          :column-key="item.prop"
          :filters="item.filters"
          :fixed="item.fixed"
          :sort-orders="['ascending', 'descending']"
        >
          <template v-slot:header="scope">
            <span
              v-if="scope.column.label && scope.column.label.indexOf('<') > -1"
              v-html="scope.column.label"
            ></span>
            <span v-else :title="scope.column.label">{{ scope.column.label }}</span>
          </template>
          <template v-slot="scope">
            <span
              style="width: 100%"
              @click="
                item.event &&
                  $emit('column-click', item.event, {
                    row: scope.row,
                    option: item,
                    value: scope.row[item.prop],
                    $rowMsg: {
                      column: scope.column,
                      index: scope.$index,
                      page: currentPage,
                      size: pageSize,
                    },
                  })
              "
              v-html="
                item.formatter({
                  row: scope.row,
                  option: item,
                  value: specialSymbolFiltering(scope.row[item.prop]),
                  scope,
                })
              "
            />
          </template>
        </el-table-column>
        <!-- 需要写入插槽的内容 -->
        <el-table-column
          v-else-if="item.slot"
          :key="index"
          :prop="item.prop"
          :label="item.label"
          :sortable="item.sortable"
          :align="item.align"
          :width="dealWidth(item.width)"
          :min-width="dealWidth(item.minWidth)"
          :column-key="item.prop"
          :filters="item.filters"
          :fixed="item.fixed"
          :sort-orders="['ascending', 'descending']"
        >
          <template v-slot:header="scope">
            <span
              v-if="scope.column.label && scope.column.label.indexOf('<') > -1"
              v-html="scope.column.label"
            ></span>
            <span v-else :title="scope.column.label">{{ scope.column.label }}</span>
          </template>
          <template v-slot="scope">
            <slot
              :name="item.slot"
              :data="{
                row: scope.row,
                option: item,
                value: scope.row[item.prop],
                $rowMsg: {
                  column: scope.column,
                  index: scope.$index,
                  page: currentPage,
                  size: pageSize,
                },
              }"
            ></slot>
          </template>
        </el-table-column>
        <!-- 原样显示 -->
        <el-table-column
          v-else
          :key="index + '-d'"
          :prop="item.prop"
          :label="item.label"
          :sortable="item.sortable"
          :width="dealWidth(item.width)"
          :align="item.align"
          :min-width="dealWidth(item.minWidth)"
          :column-key="item.prop"
          :filters="item.filters"
          :fixed="item.fixed"
          :sort-orders="['ascending', 'descending']"
        >
          <template v-slot:header="scope">
            <span
              v-if="scope.column.label && scope.column.label.indexOf('<') > -1"
              v-html="scope.column.label"
            ></span>
            <span v-else :title="scope.column.label">{{ scope.column.label }}</span>
          </template>
          <template v-slot="scope">
            <span
              :title="scope.row[item.prop]"
              style="overflow: hidden; text-overflow: ellipsis; white-space: nowrap"
              >{{ scope.row[item.prop] }}</span
            >
          </template>
        </el-table-column>
      </template>
    </el-table>
    <ehl-page
      v-if="usePage && total !== 0"
      class="_ehl_pagination"
      :current-page="currentPage"
      :page-sizes="pageSizes"
      :page-size="pageSize"
      :total="total"
      :layout="layout"
      :position="position"
      :small="small"
      @size-change="sizeChange"
      @current-change="pageChange"
    ></ehl-page>
  </div>
</template>
<script>
  import Vue from 'vue'
  import { Table, TableColumn } from 'element-ui'
  Vue.use(Table)
  Vue.use(TableColumn)
  export default {
    name: 'ehlTable',
    components: { ehlPage: () => $import('ehlPage') },
    props: {
      tableData: {
        type: Array,
        default: () => [],
      },
      tableColumns: {
        type: Array,
        default: () => [],
      },
      defaultSort: {
        type: String,
        default: () => '',
      },
      rowKey: {
        type: String,
        default: () => 'id',
      },
      filterSingle: {
        type: Boolean,
        default: () => true, //true:多选项同时，false:单选项
      },
      maxHeight: {
        type: Number,
        default: () => 1000,
      },
      usePage: {
        type: Boolean,
        default: () => true,
      },
      border: {
        type: Boolean,
        default: () => false,
      },
      currentPage: {
        type: Number,
        default: () => 1,
      },
      pageSize: {
        type: Number,
        default: () => 10,
      },
      pageSizes: {
        type: Array,
        default: () => [10, 20, 50, 100],
      },
      total: {
        type: Number,
        default: () => 0,
      },
      layout: {
        type: String,
        default: () => 'total, sizes, prev, pager, next, jumper',
      },
      position: {
        type: String,
        default: () => 'right',
      },
      //分页是不是小型化
      small: {
        type: Boolean,
        default: () => false,
      },
      // 行类名
      rowClassName: {
        type: Function,
        default: ({ row, rowIndex }) => {
          if (rowIndex % 2 === 1) {
            return '_ehltable_odd_row' // 奇数行类名
          } else if (rowIndex % 2 === 0) {
            return '_ehltable_even_row' // 偶数行类名
          }
          return ''
        },
      },
    },
    computed: {
      indeterminate() {
        let tmp = false
        let tmp1 = true
        this.tableData.forEach(element => {
          if (element.checked) {
            tmp = true
          } else {
            tmp1 = false
          }
        })
        return tmp && !tmp1
      },
      allSelect: {
        get() {
          let tmp = true
          //数组为空多选为空
          if (isEmpty(this.tableData) || this.tableData.length === 0) {
            return false
          }
          //多选状态取决于下面所有数据
          this.tableData.forEach(element => {
            tmp = element.checked && tmp
          })
          return tmp
        },
        set(newValue) {
          this.tableData.forEach(element => {
            element.checked = newValue
          })
        },
      },
    },
    data() {
      return {
        ref: `table_ref_${Math.random()}`,
        filterAll: {},
        filterAllJSON: null,
      }
    },
    created() {
      //只有第一次加载表格在会判断是否需要增加多选框
      if (
        !isEmpty(this.tableData) &&
        this.tableData.length > 0 &&
        this.tableData[0].checked !== undefined &&
        this.tableColumns[0].checked === undefined
      ) {
        this.tableColumns.unshift({
          checked: true,
          prop: 'checked',
        })
      }
      //适配老数据，整理过滤返回结果
      this.tableColumns.forEach(i => {
        if (i.filters) {
          this.filterAll[i.prop] = {
            selectedValues: i.filters.map(t => {
              return t.value
            }),
          }
        }
      })
      this.$emit('init', this.tableColumns, this.tableData)
    },
    methods: {
      specialSymbolFiltering(val) {
        if (typeof val === 'string') {
          val = val.replace(/</g, `&lt;`)
          val = val.replace(/>/g, `&gt;`)
          val = val.replace(/"/g, `&quot;`)
        }
        return val
      },
      clearState() {
        this.$refs[this.ref].clearSort()
        this.$refs[this.ref].clearFilter()
        if (this.filterAllJSON) {
          this.filterAll = JSON.parse(JSON.stringify(this.filterAllJSON))
        }
      },
      fromatEvent(item, scope) {
        item.event && item.event.call(this.$parent, scope.row, item, scope.row[item.prop])
      },
      dealWidth(str) {
        if (str && str.toString().indexOf('%') === -1) {
          return str.toString()
        }
        return 'auto'
      },
      checkboxChange(val, item, scope) {
        this.tableData.forEach(element => {
          element.checked = val
        })
        item.event && item.event(val, this.tableData)
      },
      selectionChange(selection) {
        this.$emit('selection-change', selection, this.tableColumns, this.tableData)
      },
      pageChange(page) {
        this.$emit('page-change', page, this.tableColumns, this.tableData)
      },
      sizeChange(size) {
        this.$emit('size-change', size, this.tableColumns, this.tableData)
      },
      sortHandler(value) {
        let tmp = {
          field: value.prop,
          order: value.order === 'ascending' ? 'asc' : 'desc',
        }
        console.log(tmp)
        this.$emit('sort', tmp.order, tmp.field, this.tableColumns, this.tableData)
      },
      filterHandler(filters) {
        let that = this
        if (!this.filterAllJSON) {
          this.filterAllJSON = JSON.parse(JSON.stringify(this.filterAll))
        }
        let filterArr = Object.values(filters)[0]
        let filterKey = Object.keys(filters)[0]
        let tmp = null
        //如果有筛选条件则使用，条件为空，传给后端全集
        if (filterArr.length > 0) {
          tmp = { [filterKey]: { selectedValues: filterArr } }
        } else {
          tmp = {
            [filterKey]: { selectedValues: this.filterAllJSON[filterKey].selectedValues },
          }
        }
        if (this.filterSingle) {
          tmp = Object.assign({}, this.filterAll, tmp) //单类型筛选
          Object.keys(this.filterAll).forEach(key => {
            if (key !== filterKey) {
              that.$refs[that.ref].clearFilter(key)
            }
          })
        } else {
          tmp = Object.assign(this.filterAll, tmp) //全部筛选
        }
        this.$emit('filter-change', tmp, this.tableColumns, this.tableData)
      },
    },
  }
</script>
